package com.ayz.gateway.core.session.executor;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.log.Log;
import com.ayz.gateway.common.result.GatewayResult;
import com.ayz.gateway.common.result.ResponseCode;
import com.ayz.gateway.core.datasource.Connection;
import com.ayz.gateway.core.datasource.Datasource;
import com.ayz.gateway.core.datasource.DatasourceFactory;
import com.ayz.gateway.core.datasource.RpcStatement;
import com.ayz.gateway.core.session.GatewaySession;
import com.ayz.gateway.core.session.processor.RpcPostProcessor;
import lombok.Data;

import java.util.concurrent.CompletableFuture;

/**
 * @ClassName DefaultExecutor
 * @Description TODO: 默认的执行器 默认一次HTTP请求开启一次会话 一次会话一个RPC执行器
 * @Author 快乐的星球
 * @Date 2023/5/10 18:16
 * @Version 1.0
 **/
@Data
public class DefaultExecutor extends AbstractExecutor{
    /**
     * 网关会话
     */
    private GatewaySession gatewaySession;

    private static final Log LOG=Log.get(DefaultExecutor.class);

    public DefaultExecutor(GatewaySession gatewaySession) {
        this.gatewaySession = gatewaySession;
    }

    @Override
    public void execute(RpcStatement rpcStatement) {
        //前置增强处理
        RpcPostProcessor[] rpcPostProcessors = gatewaySession.getRpcPostProcessors();
        if(ArrayUtil.isNotEmpty(rpcPostProcessors)){
            int size = rpcPostProcessors.length;
            for(int i=0;i<size;i++){
                try {
                    boolean intercept=rpcPostProcessors[i].before(gatewaySession,rpcStatement);
                    if(!intercept){
                        handleResult(GatewayResult.error(ResponseCode.BE_INTERCEPTED,"当前RPC执行计划被拦截器拦截了!"), rpcStatement.getResponseCallback());
                        return;
                    }
                } catch (Exception e) {
                    LOG.warn("RpcPostProcessor执行失败!");
                    handleResult(GatewayResult.error(ResponseCode.BE_INTERCEPTED,"当前RPC执行计划被拦截器拦截了!"), rpcStatement.getResponseCallback());
                    return;
                }
            }
        }
        //1:获取数据源工厂
        DatasourceFactory datasourceFactory = rpcStatement.getDatasourceFactory();
        //2:获取RPC连接数据源
        Datasource datasource = datasourceFactory.getDatasource();
        //3:获取RPC连接
        Connection connection = datasource.getConnection();
        GatewayResult gatewayResult = null;
        try {
            Object res = connection.execute(rpcStatement);
            //4: 根据是同步还是异步进行相应的处理
            boolean sync = rpcStatement.isSync();
            if(sync){
                //是同步
                gatewayResult =GatewayResult.success(res);
                invokedAfterPostProcessor(rpcPostProcessors,gatewayResult,rpcStatement);
                handleResult(gatewayResult, rpcStatement.getResponseCallback());
            }else {
                //异步
                CompletableFuture<Object> completableFuture=(CompletableFuture<Object>) res;
                completableFuture.whenComplete((result,ex)->{
                    GatewayResult gr=null;
                    if(ex!=null){
                        //出现了错误
                        gr=GatewayResult.error(ex.getMessage());
                    }else {
                        gr=GatewayResult.success(result);
                        invokedAfterPostProcessor(rpcPostProcessors,gr,rpcStatement);
                    }
                    handleResult(gr, rpcStatement.getResponseCallback());
                });
            }
        } catch (Exception e) {
            gatewayResult=GatewayResult.error(e.getMessage());
            handleResult(gatewayResult, rpcStatement.getResponseCallback());
        }
    }

    protected void invokedAfterPostProcessor(RpcPostProcessor[] postProcessors,GatewayResult gatewayResult,RpcStatement rpcStatement){
        if(ArrayUtil.isNotEmpty(postProcessors)){
            int size=postProcessors.length;
            for(int i=0;i<size;i++){
                try {
                    postProcessors[i].after(gatewaySession,rpcStatement,gatewayResult);
                } catch (Exception e) {
                    LOG.warn("RpcPostProcessor 的after逻辑执行失败!");
                    return;
                }
            }
        }
    }
}
